package com.lcredu.annotation.myonly;

import com.lcredu.annotation.ComponentScan;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.io.File;
import java.lang.annotation.Annotation;
import java.net.URL;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author 黎长容
 * @date 2025-07-14 16:39
 * 充当容器类,类似 Spring 原生的 ApplicationContext
 */

public class MyApplicationContext {
    private Class configClass;
    //储存表
    private final ConcurrentHashMap<String, Object> singletonObjects = new ConcurrentHashMap<>();

    public MyApplicationContext(Class configClass) {
        this.configClass = configClass;

        //1.获取要扫描的包
        MyComponentScan componentScan = (MyComponentScan) this.configClass.getDeclaredAnnotation(MyComponentScan.class);
        String path = componentScan.value();
        System.out.println("path=" + path);

        //2.获取class
        //(1) 获取类的加载器
        ClassLoader classLoader = MyApplicationContext.class.getClassLoader();
        path = path.replace(".", "/");
        //(2)  通过类的加载器获取到要扫描包的URL
        URL resource = classLoader.getResource(path);
        System.out.println(resource);
        //(3) 将要加载的资源(.class)进行遍历=>io
        File file = new File(resource.getFile());
        if (file.isDirectory()) {
            File[] files = file.listFiles();
            //循环遍历所有的class
            for (File f : files) {
                //                System.out.println(f);
                System.out.println("===================================");
                //获取绝对路径
                String filePath = f.getAbsolutePath();
                System.out.println(filePath);
                //判断是不是.class文件
                if (filePath.endsWith(".class")) {
                    //如果是就取出类名
                    String className = filePath.substring(filePath.lastIndexOf("\\") + 1, filePath.indexOf(".class"));
                    System.out.println("className=" + className);
                    //再拼装类的全路径
                    path = path.replace("/", ".");
                    String fileFullPath = path + "." + className;
                    //判断是不是需要反射的类
                    try {
                        Class<?> aClass = classLoader.loadClass(fileFullPath);
                        if (aClass.isAnnotationPresent(Controller.class) || aClass.isAnnotationPresent(Service.class)
                                || aClass.isAnnotationPresent(Repository.class) || aClass.isAnnotationPresent(Component.class)) {

                            //如何设置id
                            if (aClass.isAnnotationPresent(Controller.class)) {
                                Controller controller = aClass.getDeclaredAnnotation(Controller.class);
                                String id = controller.value();
                                if (!"".equals(id)){
                                    className = id;
                                }
                            }

                            //如果是有这四个注解的类,就反射
                            //StringUtils.capitalize() : 首字母小写
                            Class<?> clazz = Class.forName(fileFullPath);
                            Object object = clazz.newInstance();
                            singletonObjects.put(StringUtils.uncapitalize(className), object);
                        }
                    } catch (Exception e) {
                        throw new RuntimeException(e);
                    }
                }
            }
        }


    }

    public Object getBean(String id) {
        return singletonObjects.get(id);
    }
}
